package com.javabi.codegenerator.java.object.id;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.javabi.codegenerator.model.IModel;
import com.javabi.codegenerator.model.object.IModelObject;

public class ModelIdRegistry {

	private static final Logger log = LoggerFactory.getLogger(ModelIdRegistry.class);

	private final Map<Class<? extends IModelObject>, Set<Integer>> duplicateMap = new HashMap<Class<? extends IModelObject>, Set<Integer>>();

	public void setIds(IModel model) {
		int baseId = model.getId();
		if (baseId < 0) {
			throw new IllegalStateException("negative id=" + baseId);
		}
		setIds(baseId, model.getBeanList());
	}

	private synchronized void setIds(int baseId, List<? extends IModelObject> objectList) {
		int localId = 0;
		for (IModelObject object : objectList) {
			Class<? extends IModelObject> type = object.getClass();
			int id = object.getId();

			// Set id if not already set
			if (id == 0) {
				id = ++localId;
			}

			// Add base id
			id = baseId + id;

			// Check if ducplicate
			Set<Integer> duplicates = getDuplicates(type);
			if (!duplicates.add(id)) {
				throw new IllegalStateException("duplicate id " + id + " for type " + object.getClass());
			}

			// Done
			log.info(object.getName() + "@" + type.getSimpleName() + " -> " + id);
			object.setId(id);
		}
	}

	private Set<Integer> getDuplicates(Class<? extends IModelObject> type) {
		Set<Integer> set = duplicateMap.get(type);
		if (set == null) {
			set = new HashSet<Integer>();
			duplicateMap.put(type, set);
		}
		return set;
	}
}
